home *** CD-ROM | disk | FTP | other *** search
/ Best Tools for JAVA / Best Tools for JAVA.iso / JAVA_ALL / IDE / SUBARTIC / SUB_ARCT / CONSTRAI / STD_ENCO.JAV < prev    next >
Encoding:
Text File  |  1996-10-04  |  18.9 KB  |  481 lines

  1.  
  2. package sub_arctic.constraints;
  3.  
  4. import sub_arctic.lib.interactor_consts;
  5.  
  6. /**
  7.  * Interface to define standard constraint encoding constants. 
  8.  * <b>Important note</b>: you don't normally need to know or use these internal 
  9.  *  encodings.  Instead you can use the std_constraint_consts interface and 
  10.  *  std_function class which hides all the internals behind a nicer API.<p>
  11.  *
  12.  * Constraints with 0, 1, 2, or 3 operands are supported.  Operands 
  13.  * (depended upon object parts) are encoded in 6 bits with a code indicating
  14.  * which object in the upper 3 bits and a part code in the lower 3.
  15.  * Objects that can be depended upon include: self, parent, previous sibling,
  16.  * next sibling, first child, last child, min child, and max child.  Parts of
  17.  * those objects that can be depended upon include: x, y, x2 (right), y2 
  18.  * (bottom), w, h, horizontal center, vertical center, visible, enabled,
  19.  * part_a (object specific), and part_b (object specific).<p>
  20.  * 
  21.  * Constraints are internally encoded as follows:
  22.  * <pre>
  23.  *      8        6      6      6       5
  24.  *   KKKKKKKK AAAAAA BBBBBB CCCCCC 0 00000   clip(A, B+K, C-K) 
  25.  *   KKKKKKKK AAAAAA BBBBBB CCCCCC 1 00000   wrap(A, B+K, C-K) 
  26.  *                                             [K is 8 bit unsigned]
  27.  *
  28.  *             16          6     5     5
  29.  *     KKKKKKKKKKKKKKKK XXXXXX 00000 00001   64 0 operand operations
  30.  *                                             [K is 16 bit signed]
  31.  *             16          6     5     5
  32.  *     KKKKKKKKKKKKKKKK AAAAAA 00001 00001   31 1 operand operations
  33.  *                              ...            [K is 16 bit signed]
  34.  *     KKKKKKKKKKKKKKKK AAAAAA 11111 00001   
  35.  *
  36.  *            15          6      6     5
  37.  *     KKKKKKKKKKKKKKK AAAAAA BBBBBB 00010   30 2 operand operations 
  38.  *                              ...            [K is 15 bit signed]
  39.  *     KKKKKKKKKKKKKKK AAAAAA BBBBBB 11111   
  40.  * </pre>
  41.  * Where KKK represents a constant, AAA, BBB, and CCC represent parameter
  42.  * objects, and XXX represents bits used to encode an op code.<p>
  43.  *
  44.  * @author Scott Hudson
  45.  */
  46.  
  47. public interface std_encoding_consts {
  48.  
  49.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  50.   /* Orientation codes for horizontal vs. vertical vs. other.  These are 
  51.    * used to tag constraint objects for type checking (since we disallow
  52.    * mixed orientation encodings in lightweight constraints).  These 
  53.    * constants are suitable for use as bits in a set.
  54.    */
  55.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  56.  
  57.   /** Orientation code indicating horizontal constraint. */
  58.   public static final int HORIZONTAL   = 0x1;
  59.  
  60.   /** Orientation code indicating vertical constraint. */
  61.   public static final int VERTICAL     = 0x2;
  62.  
  63.   /** Orientation code indicating constraint that is neither horizontal or 
  64.    *  vertical in nature. */
  65.   public static final int NOT_ORIENTED = 0x4;
  66.  
  67.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  68.   /* Integer encoding for object parts.  An object part encoding is placed 
  69.    * 6 bits with the high order 3 bits providing an object designator
  70.    * and the lower 3 bit holding a part designator.  Normally, this integer
  71.    * encoding is not used directly in "user code".  Instead use SELF.x(), 
  72.    * etc. defined in std_constraint_consts. */
  73.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  74.  
  75.   /** Code to reference local neighborhood object: self */
  76.   public static final int OBJCODE_SELF         = 0;
  77.  
  78.   /** Code to reference local neighborhood object: parent */
  79.   public static final int OBJCODE_PARENT       = 1;
  80.  
  81.   /** Code to reference local neighborhood object: first child */
  82.   public static final int OBJCODE_FIRST_CHILD  = 2;
  83.  
  84.   /** Code to reference local neighborhood object: last child */
  85.   public static final int OBJCODE_LAST_CHILD   = 3;
  86.  
  87.   /** Code to compute the maximum of some part among child objects */
  88.   public static final int OBJCODE_MAX_CHILD    = 4;
  89.  
  90.   /** Code to compute the minimum of some part among child objects */
  91.   public static final int OBJCODE_MIN_CHILD    = 5;
  92.  
  93.   /** Code to reference local neighborhood object: previous sibling */
  94.   public static final int OBJCODE_PREV_SIBLING = 6;
  95.  
  96.   /** Code to reference local neighborhood object: next sibling */
  97.   public static final int OBJCODE_NEXT_SIBLING = 7;
  98.  
  99.   /** Largest valid object code. */
  100.   public static final int OBJCODE_MAX = OBJCODE_NEXT_SIBLING;
  101.  
  102.   /** Mask for accessing object code in object/part encoding.  Object is 
  103.    *  accessed as (enc >> OBJCODE_SHIFT) & OBJCODE_MASK. */
  104.   public static final int OBJCODE_MASK         = 0x7;
  105.  
  106.   /** Shift value for accessing object code in object/part encoding.  Object is 
  107.    *  accessed as (enc >> OBJCODE_SHIFT) & OBJCODE_MASK. */
  108.   public static final int OBJCODE_SHIFT        = 3;
  109.  
  110.   /** Special object code to designate some child object during mark 
  111.    *  out-of-date phase. This in not used in encoding of constraints. */
  112.   public static final int OBJCODE_SOME_CHILD = OBJCODE_MAX + 1;
  113.  
  114.   /** Table of strings for object code names. */
  115.   public static final String[] OBJCODE_strings = {
  116.     "SELF", "PARENT", "FIRST_CHILD", "LAST_CHILD", "MAX_CHILD", "MIN_CHILD",
  117.     "PREV_SIBLING", "NEXT_SIBLING", "SOME_CHILD" };
  118.  
  119.   /** Table of very terse strings for object code names. */
  120.   public static final String[] OBJCODE_tags = {
  121.     "S", "P", "FC", "LC", "XC", "NC", "PS", "NS", "*C" };
  122.  
  123.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  124.  
  125.   /** Code to reference the x or y part of an object. */
  126.   public static final int PARTCODE_XY      = 0;
  127.  
  128.   /** Code to reference the x2 or y2 part of an object (which is x+w or y+h). */
  129.   public static final int PARTCODE_XY2     = 1;
  130.  
  131.   /** Code to reference the w or h part of an object */
  132.   public static final int PARTCODE_WH      = 2;
  133.  
  134.   /** Code to reference the horizontal or vertical center of an object (which 
  135.    *  is x+w/2 or y+h/2). */
  136.   public static final int PARTCODE_CENTER  = 3;
  137.  
  138.   /** Code to reference the visible part of an object */
  139.   public static final int PARTCODE_VISIBLE = 4;
  140.  
  141.   /** Code to reference the enabled part of an object */
  142.   public static final int PARTCODE_ENABLED = 5;
  143.  
  144.   /** Code to reference the part_a part of an object */
  145.   public static final int PARTCODE_PART_A  = 6;
  146.  
  147.   /** Code to reference the part_b part of an object */
  148.   public static final int PARTCODE_PART_B  = 7;
  149.  
  150.   /** Largest valid part code */
  151.   public static final int PARTCODE_MAX     = PARTCODE_PART_B;
  152.  
  153.   /** Mask to extract part code from object/part encoding.  The part is found
  154.    *  using (enc>>PARTCODE_SHIFT) & PARTCODE_MASK. */
  155.   public static final int PARTCODE_MASK    = 0x7;
  156.  
  157.   /** Shift value to extract part code from object/part encoding.  The part is 
  158.    *  found using (enc>>PARTCODE_SHIFT) & PARTCODE_MASK. */
  159.   public static final int PARTCODE_SHIFT   = 0;
  160.  
  161.   /** Table of strings for horizontal part names. */
  162.   public static final String[] PARTCODE_strings_h = {
  163.     "X", "X2", "W", "CENTER", "VISIBLE", "ENABLED", "PART_A", "PART_B" };
  164.  
  165.   /** Table of strings for vertical part names. */
  166.   public static final String[] PARTCODE_strings_v = {
  167.     "Y", "Y2", "H", "CENTER", "VISIBLE", "ENABLED", "PART_A", "PART_B" };
  168.  
  169.   /** Table of very terse strings for horizontal part names. */
  170.   public static final String[] PARTCODE_tags_h = {
  171.     "X", "X2", "W", "C", "V", "E", "PA", "PB" };
  172.  
  173.   /** Table of very terse strings for vertical part names. */
  174.   public static final String[] PARTCODE_tags_v = {
  175.     "Y", "Y2", "H", "C", "V", "E", "PA", "PB" };
  176.  
  177.   /** Mask to limit an encode to just the low order 6 bits (for an object/part
  178.    *  encoding. */
  179.   public static final int OBJPART_MASK = 0x3f;
  180.  
  181.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  182.  
  183.   /*---------------------------------------------------------------------*/
  184.   /* Constraints of various flavors are encoded as follows:
  185.    *
  186.    *      8        6      6      6       5
  187.    *   KKKKKKKK AAAAAA BBBBBB CCCCCC 0 00000   clip(A, B+K, C-K) 
  188.    *   KKKKKKKK AAAAAA BBBBBB CCCCCC 1 00000   wrap(A, B+K, C-K) 
  189.    *                                             [K is 8 bit unsigned]
  190.    *
  191.    *             16          6     5     5
  192.    *     KKKKKKKKKKKKKKKK XXXXXX 00000 00001   64 0 operand operations
  193.    *                                             [K is 16 bit signed]
  194.    *             16          6     5     5
  195.    *     KKKKKKKKKKKKKKKK AAAAAA 00001 00001   31 1 operand operations
  196.    *                              ...            [K is 16 bit signed]
  197.    *     KKKKKKKKKKKKKKKK AAAAAA 11111 00001   
  198.    *
  199.    *            15          6      6     5
  200.    *     KKKKKKKKKKKKKKK AAAAAA BBBBBB 00010   30 2 operand operations 
  201.    *                              ...            [K is 15 bit signed]
  202.    *     KKKKKKKKKKKKKKK AAAAAA BBBBBB 11111   
  203.    */
  204.   /*---------------------------------------------------------------------*/
  205.  
  206.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  207.   /* 1-bit codes for selecting 3 operand ops<p> 
  208.    *
  209.    * 3 ops are encoded as:<br>
  210.    * <pre>
  211.    *      8        6      6      6   1   5
  212.    *   KKKKKKKK AAAAAA BBBBBB CCCCCC X 00000   
  213.    * </pre>
  214.    */
  215.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  216.  
  217.   /** Shift value for extracting op codes from 3-op constraints. An op code 
  218.    *  of this type can be accessed via: (enc & OP3_MASK) >> OP3_SHIFT. */
  219.   public static final int  OP3_SHIFT = 5;
  220.  
  221.   /** Mask value for extracting op codes from 3-op constraints. An op code 
  222.    *  of this type can be accessed via: (enc & OP3_MASK) >> OP3_SHIFT. */
  223.   public static final int  OP3_MASK  = 0x20;
  224.  
  225.   /** Fixed low order bits for 3-op constraint encoding. */
  226.   public static final int  OP3_LOBITS= 0x00;
  227.  
  228.   /** Lowest valid 3-op op code */
  229.   public static final int  OP3_MIN   = 0;
  230.  
  231.   /** Op code for clip(A, B+K, C-K) */
  232.   public static final int  OP_clip = 0; // clip(A, B+K, C-K) [same 8 bit K]
  233.   /** Op code for wrap(A, B+K, C-K) */
  234.   public static final int  OP_wrap = 1; // wrap(A, B+K, C-K) 
  235.  
  236.   /** Highest valid 3-op op code */
  237.   public static final int  OP3_MAX   = 1;
  238.  
  239.   /** Table of op code name strings */
  240.   public static final String[] OP3_strings = {"clip", "wrap"};
  241.  
  242.   /** Table of terse op code name strings */
  243.   public static final String[] OP3_tags = {"clip", "wrap"};
  244.  
  245.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  246.   /* 6-bit codes for selecting 0 operand ops<p>
  247.    *
  248.    * 0 ops are encoded as:<br>
  249.    * <pre>
  250.    *             16          6     5     5
  251.    *     KKKKKKKKKKKKKKKK XXXXXX 00000 00001   64 0 operand operations
  252.    * </pre>
  253.    */
  254.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  255.  
  256.   /** Shift value for extracting op codes from 0-op constraints. An op code 
  257.    *  of this type can be accessed via: (enc & OP0_MASK) >> OP0_SHIFT. */
  258.   public static final int OP0_SHIFT = 10;
  259.  
  260.   /** Mask value for extracting op codes from 0-op constraints. An op code 
  261.    *  of this type can be accessed via: (enc & OP0_MASK) >> OP0_SHIFT. */
  262.   public static final int OP0_MASK  = 0xf400;
  263.  
  264.   /** Fixed low order bits for 0-op constraint encoding. */
  265.   public static final int OP0_LOBITS= 0x001;
  266.  
  267.   /** Lowest valid 0-op op code */
  268.   public static final int OP0_MIN   = 0;
  269.  
  270.   /** Special op code that indicates that no constraint should be applied */
  271.   public static final int OP_NONE       =  0; // no constraint 
  272.  
  273.   /** Op code that indicates a separate external (or heavyweight) constraint
  274.    *  is being applied. */
  275.   public static final int OP_external   =  1; // ext constraint
  276.  
  277.   /** Op code for a constant constraint */
  278.   public static final int OP_konst      =  2; // constant K
  279.   // ops 3..63 TBD
  280.  
  281.   /** Largest valid 0-op op code */
  282.   public static final int OP0_MAX   = 2;
  283.  
  284.   /** Table of strings for 0-op op code names */
  285.   public static final String[] OP0_strings = {"NONE", "external", "const"};
  286.  
  287.   /** Table of terse strings for 0-op op code names */
  288.   public static final String[] OP0_tags = {"NONE", "ext", "cnst"};
  289.  
  290.   /** Mask for testing none. Test is "(enc & NONE_TEST_MASK)==NONE_TEST_VAL" */
  291.   public static final int NONE_TEST_MASK = 0xffff;
  292.  
  293.   /** Value for testing none. Test is "(enc & NONE_TEST_MASK)==NONE_TEST_VAL" */
  294.   public static final int NONE_TEST_VAL  = 
  295.     (OP_NONE << OP0_SHIFT) & OP0_MASK | OP0_LOBITS;
  296.  
  297.   /** Mask for testing external.  Test is 
  298.    *  "(enc & EXTERNAL_TEST_MASK) == EXTERNAL_TEST_VAL */
  299.   public static final int EXTERNAL_TEST_MASK = 0xffff;
  300.  
  301.   /** Value for testing external. Test is 
  302.    *  "(enc & EXTERNAL_TEST_MASK) == EXTERNAL_TEST_VAL" */
  303.   public static final int EXTERNAL_TEST_VAL  = 
  304.     (OP_external << OP0_SHIFT) & OP0_MASK | OP0_LOBITS;
  305.  
  306.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  307.   /* 5-bit codes for selecting 1 operand ops<p>
  308.    *
  309.    * 1 ops are encoded as:<br>
  310.    * <pre>
  311.    *             16          6     5     5
  312.    *     KKKKKKKKKKKKKKKK AAAAAA 00001 00001   31 1 operand operations
  313.    *                              ...            [K is 16 bit signed]
  314.    *     KKKKKKKKKKKKKKKK AAAAAA 11111 00001   
  315.    * </pre>
  316.    */
  317.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  318.  
  319.   /** Shift value for extracting op codes from 1-op constraints. An op code 
  320.    *  of this type can be accessed via: (enc & OP1_MASK) >> OP1_SHIFT. */
  321.   public static final int OP1_SHIFT = 5;
  322.  
  323.   /** Mask value for extracting op codes from 1-op constraints. An op code 
  324.    *  of this type can be accessed via: (enc & OP1_MASK) >> OP1_SHIFT. */
  325.   public static final int OP1_MASK  = 0x3e0;
  326.  
  327.   /** Fixed low order bits for 1-op constraint encoding. */
  328.   public static final int OP1_LOBITS= 0x01;
  329.  
  330.   /** Lowest valid 1-op op code */
  331.   public static final int OP1_MIN   = 1;
  332.  
  333.   /** Op code for self.fun1(A,K) */
  334.   public static final int OP_self_fun1    = 1; // self.fun1(A,K)
  335.  
  336.   /** Op code for parent.fun1(A,K) */
  337.   public static final int OP_parent_fun1  = 2; // parent.fun1(A,K)
  338.  
  339.   /** Op code for ~A & (K|0xffff0000) */
  340.   public static final int OP_not_mask     = 3; // ~A & (K|0xffff0000)
  341.  
  342.   /** Op code for A & (K|0xffff0000) */
  343.   public static final int OP_mask         = 4; //  A & (K|0xffff0000)
  344.  
  345.   /** Op code for (A-self.wh)/2 + K */
  346.   public static final int OP_centered     = 5; // (A-self.wh)/2 + K
  347.  
  348.   /** Op code for A + K */
  349.   public static final int OP_offset       = 6; // A + K
  350.  
  351.   /** Op code for A - self.wh - K */
  352.   public static final int OP_far_edge_just= 7; // A - self.wh - K
  353.   // ops 8..31 TBD
  354.  
  355.   /** Largest valid 1-op op code */
  356.   public static final int OP1_MAX   = 7;
  357.  
  358.   /** Table of op code name strings */
  359.   public static final String[] OP1_strings = {
  360.     "self.fun1", "parent.fun1", "not_mask", "mask", "centered", "offset", 
  361.     "far_edge_just"};
  362.  
  363.   /** Table of terse op code name strings */
  364.   public static final String[] OP1_tags = {
  365.     "s.f1", "p.f1", "ntmsk", "msk", "cent", "off", "fej"};
  366.  
  367.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  368.   /* 5 bit codes for selecting 2 operand ops<p>                             
  369.    * <pre>
  370.    *            15          6      6     5
  371.    *     KKKKKKKKKKKKKKK AAAAAA BBBBBB 00010   30 2 operand operations 
  372.    *                              ...            [K is 15 bit signed]
  373.    *     KKKKKKKKKKKKKKK AAAAAA BBBBBB 11111   
  374.    * </pre>
  375.    */
  376.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  377.  
  378.   /** Shift value for extracting op codes from 2-op constraints. An op code 
  379.    *  of this type can be accessed via: (enc & OP2_MASK) >> OP2_SHIFT. */
  380.   public static final int OP2_SHIFT = 0;
  381.  
  382.   /** Mask value for extracting op codes from 2-op constraints. An op code 
  383.    *  of this type can be accessed via: (enc & OP2_MASK) >> OP2_SHIFT. */
  384.   public static final int OP2_MASK  = 0x1f;
  385.  
  386.   /** Fixed low order bits for 2-op constraint encoding. */
  387.   public static final int OP2_LOBITS= 0;
  388.  
  389.   /** Lowest valid 2-op op code */
  390.   public static final int OP2_MIN   = 2;
  391.  
  392.   /** Op code for A + B + K */
  393.   public static final int OP_add = 2;          // A + B + K
  394.  
  395.   /** Op code for A - B + K */
  396.   public static final int OP_subtract = 3;     // A - B + K
  397.  
  398.   /** Op code for A * B + K */
  399.   public static final int OP_mult = 4;         // A * B + K
  400.  
  401.   /** Op code for A / B + K */
  402.   public static final int OP_div = 5;          // A / B + K
  403.  
  404.   /** Op code for A % B + K */
  405.   public static final int OP_mod = 6;          // A % B + K
  406.  
  407.   /** Op code for A & B & (K | 0xffff8000) */
  408.   public static final int OP_and = 7;          // A & B & (K | 0xffff8000)
  409.  
  410.   /** Op code for (A | B) & (K | 0xffff8000) */
  411.   public static final int OP_or = 8;           // (A | B) & (K | 0xffff8000)
  412.  
  413.   /** Op code for A ^ B) & (K | 0xffff8000) */
  414.   public static final int OP_xor = 9;          // (A ^ B) & (K | 0xffff8000)
  415.  
  416.   /** Op code for min(A, B) + K */
  417.   public static final int OP_min = 10;         // min(A, B) + K
  418.  
  419.   /** Op code for max(A, B) + K */
  420.   public static final int OP_max = 11;         // max(A, B) + K
  421.  
  422.   /** Op code for (A + B)/2 + K */
  423.   public static final int OP_ave = 12;         // (A + B)/2 + K
  424.  
  425.   /** Op code for rotate_x(theta, B)+K */
  426.   public static final int OP_rotx = 13;        // rotate_x(theta, B)+K
  427.  
  428.   /** Op code for rotate_y(theta, B)+K */
  429.   public static final int OP_roty = 14;        // rotate_y(theta, B)+K
  430.  
  431.   /** Op code for (if enabled then A else B) + K */
  432.   public static final int OP_if_enabled = 15;  // (if enabled then A else B) + K
  433.  
  434.   /** Op code for (if visible then A else B) + K */
  435.   public static final int OP_if_visible = 16;  // (if visible then A else B) + K
  436.  
  437.   /** Op code for self.fun2(A, B, K) */
  438.   public static final int OP_self_fun2 = 17;   // self.fun2(A, B, K)
  439.  
  440.   /** Op code for parent.fun2(A, B, K) */
  441.   public static final int OP_parent_fun2 = 18; // parent.fun2(A, B, K)
  442.  
  443.   /** Op code for B - A - K */
  444.   public static final int OP_fill        = 19; // B - A - K
  445.  
  446.   // ops 20..31 TBD
  447.  
  448.   /** The largest valid 2-op op code */
  449.   public static final int OP2_MAX   = 19;
  450.  
  451.   /** Table of op code name strings. */
  452.   public static final String[] OP2_strings = {
  453.     "add", "subtract", "mult", "div", "mod", "and", "or", "xor", "min", "max",
  454.     "ave", "rotx", "roty", "if_enabled", "if_visible", "self.fun2", 
  455.     "parent.fun2", "fill"};
  456.  
  457.   /** Table of terse op code name strings. */
  458.   public static final String[] OP2_tags = {
  459.     "add", "sub", "mul", "div", "mod", "and", "or", "xor", "min", "max",
  460.     "ave", "rotx", "roty", "ifen", "ifvis", "s.f2", "p.f2", "fil"};
  461.  
  462.   /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
  463. }
  464.  
  465. /*=========================== COPYRIGHT NOTICE ===========================
  466.  
  467. This file is part of the subArctic user interface toolkit.
  468.  
  469. Copyright (c) 1996 Scott Hudson and Ian Smith
  470. All rights reserved.
  471.  
  472. The subArctic system is freely available for most uses under the terms
  473. and conditions described in 
  474.   http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html 
  475. and appearing in full in the lib/interactor.java source file.
  476.  
  477. The current release and additional information about this software can be 
  478. found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
  479.  
  480. ========================================================================*/
  481.